/**
 * 
 */
package org.dragonfire.dasm.linkers;

import java.util.HashMap;
import java.util.List;

import org.dragonfire.dasm.DASM;

/**
 * @author Darth Android
 * @date Aug 23, 2007
 */
public abstract class Linker {

	public static final String PREFIX = "Linker";
	private static HashMap<String, Linker> linkers = new HashMap<String, Linker>();

	public static Linker getInstance(String name) {
		if (name == null)
			throw new IllegalArgumentException("Linker name may not be null.");
		name = name.toUpperCase();
		if (!linkers.containsKey(PREFIX.toUpperCase() + name))
			try {
				loadInternalLinker(name.charAt(0) + name.toLowerCase().substring(1));
			} catch (Exception e) {
				throw new RuntimeException("Unknown linker '" + name + "' or it failed to load.");
			}
		return linkers.get(PREFIX.toUpperCase() + name.toUpperCase());
	}

	public static void loadLinker(String name) {
		try {
			Class linker = ClassLoader.getSystemClassLoader().loadClass(name);
			Linker d = (Linker) linker.newInstance();
			name = d.getClass().getSimpleName().toUpperCase();
			if (!linkers.containsKey(name))
				linkers.put(name, d);
			else
				throw new RuntimeException("Linker '" + name + "' already loaded.");
		} catch (ClassNotFoundException cnfe) {
			throw new IllegalArgumentException("Unknown linker '" + name + "'");
		} catch (Exception e) {
			if (e instanceof RuntimeException)
				throw (RuntimeException) e;
			throw new IllegalArgumentException("Error loading linker '" + name + "'");
		}
	}

	public abstract List<Byte> link(DASM comp, List<Byte> data);

	public static List<Byte> link(DASM comp, List<Byte> data, String format) {
		return getInstance(format).link(comp, data);
	}

	public static void loadInternalLinker(String name) {
		loadLinker("org.dragonfire.dasm.linkers." + PREFIX + name);
	}
}
